﻿//     Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using GatewayTests.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace GatewayTests.Utils
{
    public static class UrlTestsLoader
    {
        public static UrlTests LoadTests()
        {
            var configLocation = HttpContext.Current.Request.QueryString["ConfigLocation"];
            
            if (configLocation == null) {
                configLocation = ConfigurationManager.AppSettings.Get("DefaultUrlTestsLocation");
            }

            var urlTests = ReadFromStorage(configLocation);

            return urlTests;
        }
        public static UrlTests ReadFromStorage(string testsLocation)
        {
            if (String.IsNullOrWhiteSpace(testsLocation))
            {
                throw new ArgumentNullException("testsLocation", "No value specified for stored tests location");
            }
            Uri indexUri;
            if (!Uri.TryCreate(testsLocation, UriKind.Absolute, out indexUri))
            {
                throw new ArgumentException(String.Format("Specified tests location is invalid: [{0}]", testsLocation));
            }
            UrlTests parsedTests = null;
            try
            {
                parsedTests = ReadObjectFromBlob<UrlTests>(indexUri);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Failed to read remote tests configuration.", ex);
            }
            if (parsedTests == null)
            {
                throw new ArgumentException(String.Format("Failed to read remote configuration from {0}. This may be from incorrect syntax in the JSON configuration.", testsLocation));
            }

            return parsedTests;
        }

        static JsonSerializerSettings GetSerializerSettings(Uri blobLocation)
        {
            return new JsonSerializerSettings
            {
                Error = (sender, args) =>
                {
                    Trace.TraceWarning("Error deserializing JSON object [{0}]. Details: {1}", blobLocation, args.ErrorContext.Error.Message);
                    args.ErrorContext.Handled = true;
                }
            };
        }

        static JObject ReadJsonFromBlob(Uri blobLocation)
        {
            return ReadJsonFromBlob<JObject>(blobLocation, reader => JObject.Load(reader));
        }

        static T ReadObjectFromBlob<T>(Uri blobLocation)
        {
            return ReadJsonFromBlob<T>(blobLocation, reader => JsonSerializer.Create(GetSerializerSettings(blobLocation)).Deserialize<T>(reader));
        }

        static T ReadJsonFromBlob<T>(Uri blobLocation, Func<JsonReader, T> deserializer)
        {
            try
            {
                var request = (HttpWebRequest)HttpWebRequest.Create(blobLocation);
                using (var response = request.GetResponse() as HttpWebResponse)                
                {
                    return deserializer(new JsonTextReader(new StreamReader(response.GetResponseStream())));
                }
            }
            catch (Exception ex)
            {
                Trace.TraceWarning("Failure reading JSON configuration [{0}]. Details: {1}", blobLocation, ex);
                throw;
            }
        }
    }
}
